//Author wujp   标绘鼠标交互工具类
//create date 2022/6/9 10:42:32
//modify by d3kit date 2022/6/10 10:30:18
import CesiumUtil from "./cesiumUtil";
export default class Draw {
    constructor(viewer) {
        this._viewer = viewer;
        this._drawLayer = new Cesium.CustomDataSource('drawLayer')
        this._viewer.dataSources.add(this._drawLayer);
        this._handlers = null;
        this.util = new CesiumUtil(viewer);
    }

    /**
    * 画点
    * @param {*} options 
    */
    drawPointGraphics(options) {
        this._handlers && this._handlers.destroy();
        options = options || {}
        options.style = options.style ||
        {
            image: "",
            width: 35,
            height: 40,
            clampToGround: true,
            scale: 1,
            pixelOffset: new Cesium.Cartesian2(0, -20),
        }

        if (this._viewer && options) {
            var position, positions = [], poiObj, $this = this;
            this._handlers = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas);

            this._handlers.setInputAction(function (movement) {
                $this._handlers.destroy()
                $this._handlers = null
                var cartesian = $this.util.getCatesian3FromPX(movement.position);
                if (cartesian && cartesian.x) {
                    position = cartesian
                    positions.push(cartesian)
                }
                if (typeof options.callback === 'function') {
                    options.callback(positions, poiObj);
                }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            // // left
            // this._handlers.setInputAction(function (movement) {
            //     if ($this.isNearPoint(movement)) return;
            //     var cartesian = $this.util.getCatesian3FromPX(movement.endPosition);
            //     if (cartesian && cartesian.x) {
            //         position = cartesian

            //         positions.push(cartesian)
            //     }
            // }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
            // // right
            // this._handlers.setInputAction(function (movement) {

            //     $this._handlers.destroy()
            //     $this._handlers = null

            //     if (typeof options.callback === 'function') {

            //         options.callback(positions, poiObj);
            //     }
            // }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
            if (options.noEntity) return;//只取点， 不绘制entity
            let _poiEntity = new Cesium.Entity();
            _poiEntity.billboard = options.style
            _poiEntity.position = new Cesium.CallbackProperty(function () {
                return position
            }, false)
            poiObj = this._drawLayer.entities.add(_poiEntity)
        }
    }

    /**
     * 画线
     * @param {*} options 
     */
    drawLineGraphics(options) {
        this._handlers && this._handlers.destroy();
        options = options || {}
        if (this._viewer && options) {

            var positions = [], _lineEntity = new Cesium.Entity(), $this = this, lineObj;
            this._handlers = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas);
            // left
            this._handlers.setInputAction(function (movement) {
                if ($this.isNearPoint(movement)) return;
                var cartesian = $this.util.getCatesian3FromPX(movement.position);
                if (cartesian && cartesian.x) {
                    if (positions.length == 0) {
                        positions.push(cartesian.clone());
                    }
                    // 绘制直线 两个点
                    if (positions.length == 2 && options.type === "straightLine") {
                        $this._handlers.destroy()
                        $this._handlers = null
                        if (typeof options.callback === 'function') {
                            options.callback(positions, lineObj);
                        }
                    }
                    positions.push(cartesian);
                }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            this._handlers.setInputAction(function (movement) {

                var cartesian = $this.util.getCatesian3FromPX(movement.endPosition);
                if (positions.length >= 2) {
                    if (cartesian && cartesian.x) {
                        positions.pop();
                        positions.push(cartesian);
                    }
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
            this._handlers.setInputAction(function (movement) {
                $this._handlers.destroy()
                $this._handlers = null
                if (positions.length >= 2) {
                    positions.pop();
                }
                if (typeof options.callback === 'function') {
                    options.callback(positions, lineObj);
                }
            }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

            _lineEntity.polyline = {
                width: options.width || 5
                , material: options.material || Cesium.Color.BLUE.withAlpha(0.8)
                , clampToGround: options.clampToGround || false
                , clampToS3M: options.clampToS3M || false
            }
            _lineEntity.polyline.positions = new Cesium.CallbackProperty(function () {
                return positions
            }, false)
            lineObj = this._drawLayer.entities.add(_lineEntity)
        }
    }

    /**
     * 画面
     * @param {*} options 
     */
    drawPolygonGraphics(options) {
        //解决entity 自动左键双击自动定位到视图中心问题
        this._viewer.screenSpaceEventHandler.setInputAction(this.empityFun, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        this._handlers && this._handlers.destroy();
        options = options || {}
        options.style = options.style ||
        {
            width: 3
            , material: Cesium.Color.BLUE.withAlpha(0.8)
            , clampToGround: true
        }
        if (this._viewer && options) {

            var positions = [], polygon = new Cesium.PolygonHierarchy(), _polygonEntity = new Cesium.Entity(), $this = this, polyObj = null;
            this._handlers = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas);
            // left
            this._handlers.setInputAction(function (movement) {
                if ($this.isNearPoint(movement)) return;
                var cartesian = $this.util.getCatesian3FromPX(movement.position);
                
                if (cartesian && cartesian.x) {
                
                    if (positions.length == 0) {
                        polygon.positions.push(cartesian.clone())
                        positions.push(cartesian.clone());
                    }
                    positions.push(cartesian.clone());
                    polygon.positions.push(cartesian.clone())

                    if (!polyObj) create()
                }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
            // mouse
            this._handlers.setInputAction(function (movement) {

                var cartesian = $this.util.getCatesian3FromPX(movement.endPosition);
                if (positions.length >= 2) {
                    if (cartesian && cartesian.x) {
                        positions.pop()
                        positions.push(cartesian);
                        polygon.positions.pop()
                        polygon.positions.push(cartesian);
                    }
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

            // right
            this._handlers.setInputAction(function (movement) {
                $this._handlers.destroy();
                $this._handlers = null
                positions.push(positions[0]);

                if (options.height) { //立体
                    _polygonEntity.polygon.extrudedHeight = options.height
                    _polygonEntity.polygon.material = Cesium.Color.BLUE.withAlpha(0.5)
                }

                if (typeof options.callback === 'function') {
                    
                    options.callback(positions, polyObj);
                    $this._viewer.screenSpaceEventHandler.removeInputAction($this.empityFun, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
                }
            }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

            function create() {
                _polygonEntity.polyline = options.style

                _polygonEntity.polyline.positions = new Cesium.CallbackProperty(function () {
                    return positions
                }, false)

                _polygonEntity.polygon = {

                    hierarchy: new Cesium.CallbackProperty(function () {
                        return polygon
                    }, false),

                    material: Cesium.Color.WHITE.withAlpha(0.2)
                    , clampToGround: options.clampToGround || false
                }
                // _polygonEntity.clampToS3M = true

                polyObj = $this._drawLayer.entities.add(_polygonEntity)
            }
        }

    }

    empityFun() {

    }

    /**
     * 画矩形
     * @param {*} options 
     */
    drawRectangleGraphics(options) {
        this._handlers && this._handlers.destroy();
        options = options || {}
        options.style = options.style ||
        {
            width: 3
            , material: Cesium.Color.BLUE.withAlpha(0.8)
            , clampToGround: true
        }
        if (this._viewer && options) {

            var _positions = [], _rectangleEntity = new Cesium.Entity(), _coordinates = new Cesium.Rectangle(), $this = this, rectangleObj;
            this._handlers = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas);
            // left
            this._handlers.setInputAction(function (movement) {
                if ($this.isNearPoint(movement)) return;
                var cartesian = $this.util.getCatesian3FromPX(movement.position);
                if (cartesian && cartesian.x) {

                    if (_positions.length == 0) {

                        _positions.push(cartesian.clone());
                    } else {
                        $this._handlers.destroy();
                        $this._handlers = null;
                        _positions.push(cartesian.clone());

                        _coordinates = Cesium.Rectangle.fromCartesianArray([..._positions, cartesian], Cesium.Ellipsoid.WGS84)

                        if (typeof options.callback === 'function') {

                            options.callback(_positions, rectangleObj);
                        }
                    }
                }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
            // mouse
            this._handlers.setInputAction(function (movement) {

                var cartesian = $this.util.getCatesian3FromPX(movement.endPosition);

                if (cartesian) {

                    _coordinates = Cesium.Rectangle.fromCartesianArray([..._positions, cartesian], Cesium.Ellipsoid.WGS84)

                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

            _rectangleEntity.rectangle = {
                material: Cesium.Color.WHITE.withAlpha(0.2),
                clampToGround: options.clampToGround || false
            }

            _rectangleEntity.polyline = options.style

            _rectangleEntity.polyline.positions = new Cesium.CallbackProperty(() => {
                if (_positions.length < 2) {
                    return
                }

                let jwdpos = this.util.transformCartesianArrayToWGS84Array(_positions).map(el => { return [el.lng, el.lat] })
                let minx = jwdpos[0][0]
                let maxx = jwdpos[1][0]
                let miny = jwdpos[0][1]
                let maxy = jwdpos[1][1]

                let cartesianpos = [
                    minx, miny,
                    minx, maxy,
                    maxx, maxy,
                    maxx, miny,
                    minx, miny,
                ]

                return Cesium.Cartesian3.fromDegreesArray(cartesianpos)
            }, false)

            if (options.height) _rectangleEntity.rectangle.extrudedHeight = options.height
            _rectangleEntity.rectangle.coordinates = new Cesium.CallbackProperty(function () {
                return _coordinates
            }, false)
            rectangleObj = this._drawLayer.entities.add(_rectangleEntity)
        }
    }

    /**
     * 画圆
     * @param {*} options 
     */
    drawCircleGraphics(options) {
        this._handlers && this._handlers.destroy();
        options = options || {}
        options.style = options.style ||
        {
            width: 3
            , material: Cesium.Color.BLUE.withAlpha(0.5)
            , clampToGround: true
        }
        if (this._viewer && options) {

            var _center = undefined, _circleEntity = new Cesium.Entity(), $this = this, circleObj, _radius = 1;
            this._handlers = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas);

            // 计算半径
            function computeRadius(src, dest) {
                let srcCartographic = Cesium.Cartographic.fromCartesian(src)
                let destCartographic = Cesium.Cartographic.fromCartesian(dest)
                let geodesic = new Cesium.EllipsoidGeodesic()
                geodesic.setEndPoints(srcCartographic, destCartographic)
                let s = geodesic.surfaceDistance
                _radius = Math.sqrt( //开平方
                    Math.pow(s, 2) +
                    Math.pow(destCartographic.height - srcCartographic.height, 2)
                )
            }
            //
            function drawGraphics() {

                _circleEntity.ellipse = options.style
                _circleEntity.ellipse.semiMajorAxis = new Cesium.CallbackProperty(function () {
                    return _radius
                }, false)
                _circleEntity.ellipse.semiMinorAxis = new Cesium.CallbackProperty(function () {
                    return _radius
                }, false)
                _circleEntity.position = new Cesium.CallbackProperty(function () {
                    return _center
                }, false)

                _circleEntity.point = {
                    pixelSize: 5,
                    outlineColor: Cesium.Color.RED,
                    outlineWidth: 3
                }

                if (options.height) _circleEntity.ellipse.extrudedHeight = options.height

                circleObj = $this._drawLayer.entities.add(_circleEntity)
            }
            // left
            this._handlers.setInputAction(function (movement) {
                if ($this.isNearPoint(movement)) return;
                var cartesian = $this.util.getCatesian3FromPX(movement.position);

                if (cartesian && cartesian.x) {
                    if (!_center) {

                        _center = cartesian

                        drawGraphics()

                    } else {

                        computeRadius(_center, cartesian)

                        $this._handlers.destroy();
                        $this._handlers = null;
                        if (typeof options.callback === 'function') {

                            options.callback({ center: _center, radius: _radius }, circleObj);
                        }
                    }
                }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
            // mouse
            this._handlers.setInputAction(function (movement) {

                var cartesian = $this._viewer.scene.camera.pickEllipsoid(movement.endPosition, $this._viewer.scene.globe.ellipsoid);
                if (_center && cartesian && cartesian.x) {

                    computeRadius(_center, cartesian)
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        }
    }

    /**
   * 是否为相邻的两个点，连续单击或者双击会出现此情况
   * @param {*} movement 
   * @returns 
   */
    isNearPoint(movement) {
        //下面代码是 避免双击带来的2次click事件
        let times = new Date().getTime() - (this._last_clickTime || 0);
        if (this._last_clickTime && times < 200) {
            // 屏蔽了单击时间很近的点
            console.log(true);
            return true;
        }
        this._last_clickTime = new Date().getTime();

        if (
            this._last_clickPositionX &&
            Math.abs(this._last_clickPositionX - movement.x) < 10 &&
            Math.abs(this._last_clickPositionY - movement.y) < 10
        ) {
            console.log(true);
            // 屏蔽了单击像素很近的点
            return true;
        }
        this._last_clickPositionX = movement.x;
        this._last_clickPositionY = movement.y;
        //上面代码是 避免双击带来的2个重复点
        console.log(false);
        return false;
    }

    loadPolygon(options) {
        if (!options || !options.position || options.position.length == 0) return;
        let _polygonEntity = new Cesium.Entity()
        options.style = options.style ||
        {
            width: 3
            , material: Cesium.Color.BLUE.withAlpha(0.8)
            , clampToGround: true
        }
        _polygonEntity.polyline = options.style

        _polygonEntity.polyline.positions = options.position;

        _polygonEntity.polygon = {
            hierarchy: options.position,
            material: Cesium.Color.WHITE.withAlpha(0.1)
            , clampToGround: options.clampToGround || false
        }
        this._drawLayer.entities.add(_polygonEntity)
    }

    /**
     * 清除绘制
     */
    clearDraw() {
        this._handlers && this._handlers.destroy();
        this._drawLayer.entities.removeAll()
        this._handlers = null;
    }
    /**
     * 销毁
     */
    destroy() {
        this._handlers && this._handlers.destroy();
        this._viewer.dataSources.remove(this._drawLayer);
        this._viewer.screenSpaceEventHandler.removeInputAction(this.empityFun, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        this._handlers = null;
    }

}
